package com.atguigu.gmall.product.service.impl;

import com.atguigu.gmall.common.cache.BloomName;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.feign.search.SkuEsFeignClient;
import com.atguigu.gmall.model.list.Goods;
import com.atguigu.gmall.model.list.SearchAttr;
import com.atguigu.gmall.model.product.*;
import com.atguigu.gmall.product.mapper.*;
import com.atguigu.gmall.product.service.SkuInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.hash.BloomFilter;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author dyqstart
 * @create 2021-08-06-0:05
 * @since 1.0.0
 */
@Service
public class SkuInfoServiceImpl extends ServiceImpl<SkuInfoMapper, SkuInfo> implements SkuInfoService {

    @Autowired
    SkuInfoMapper skuInfoMapper;

    @Autowired
    SkuImageMapper skuImageMapper;

    @Autowired
    SkuAttrValueMapper skuAttrValueMapper;

    @Autowired
    SkuSaleAttrValueMapper skuSaleAttrValueMapper;

    @Qualifier(BloomName.SKU)
    @Autowired
    RBloomFilter<Object> skufilter;

    @Autowired
    SkuEsFeignClient skuEsFeignClient;

    @Autowired
    BaseTrademarkMapper baseTrademarkMapper;

    @Autowired
    BaseCategory1Mapper baseCategory1Mapper;
    @Autowired
    BaseCategory2Mapper baseCategory2Mapper;
    @Autowired
    BaseCategory3Mapper baseCategory3Mapper;

    @Autowired
    ThreadPoolExecutor executor;

    /**
     * {
     * "id":null,
     * "spuId":4,
     * "price":"1999",
     * "skuName":"小米3",
     * "weight":"1",
     * "skuDesc":"小米3",
     * "category3Id":61,
     * "skuAttrValueList":[
     * {
     * "attrId":"1",
     * "valueId":"57"
     * },
     * …
     * ],
     * "skuSaleAttrValueList":[
     * {
     * "saleAttrValueId":"18",
     * "saleAttrValueName":"红色",
     * "baseSaleAttrId":"1",
     * "saleAttrName":"选择颜色"
     * }
     * ],
     * "skuImageList":[
     * {
     * "spuImgId":33,
     * "imgName":"list.jpg",
     * "imgUrl":"http://47.93.118.241/group1/M00/00/00/L1128V47i9GARYUWAADxtUrmGBA961.jpg",
     * "isDefault":0
     * }
     * ],
     * "skuDefaultImg":null,
     * "tmId":4
     * }
     */
//    @Transactional
    @Override
    public void bigSaveInfo(SkuInfo skuInfo) {


        //1、保存skuInfo基础信息
        int insert = skuInfoMapper.insert(skuInfo);

        Long skuId = skuInfo.getId();
        //只要操作了数据库，赶紧告诉布隆，我插入了数据

        //2、保存sku图片信息
        List<SkuImage> skuImageList = skuInfo.getSkuImageList();
        if (!CollectionUtils.isEmpty(skuImageList)) {
            for (SkuImage skuImage : skuImageList) {
                skuImage.setSkuId(skuId);
                skuImageMapper.insert(skuImage);
            }
        }

        //3、保存sku的平台属性对应的所有值 sku_attr_value
        List<SkuAttrValue> skuAttrValueList = skuInfo.getSkuAttrValueList();
        if (!CollectionUtils.isEmpty(skuAttrValueList)) {
            for (SkuAttrValue skuAttrValue : skuAttrValueList) {
                skuAttrValue.setSkuId(skuId);
                skuAttrValueMapper.insert(skuAttrValue);
            }
        }

        //4、保存sku的销售属性以及值信息 sku_sale_attr_value
        List<SkuSaleAttrValue> skuSaleAttrValueList = skuInfo.getSkuSaleAttrValueList();
        if (!CollectionUtils.isEmpty(skuSaleAttrValueList)) {
            for (SkuSaleAttrValue skuSaleAttrValue : skuSaleAttrValueList) {
                skuSaleAttrValue.setSkuId(skuId);
                skuSaleAttrValue.setSpuId(skuInfo.getSpuId());
                skuSaleAttrValueMapper.insert(skuSaleAttrValue);
            }
        }

        // 让布隆过滤器保存一下
        String cacheKey = RedisConst.SKUKEY_PREFIX + skuId + RedisConst.SKUKEY_SUFFIX;
        skufilter.add(cacheKey);
    }

    /**
     * 事务+远程调用
     * 本地事务：长事务
     * RPC..
     * 1）事务里面不要写远程调用，分布式系统下不可避免的时候，远程做成异步编排，不阻塞数据库事务
     * 2）分布式事务
     * 商品上架下架
     * 并进行异步任务编排
     *
     * @param skuId
     * @return
     */
    @Override
    public boolean onSale(Long skuId) {

        skuInfoMapper.updateSkuSaleStatus(skuId, 1);

        // 1、把商品信息同步到搜索引擎
        Goods goods = new Goods();
        //TODO 2、把商品信息同步到搜索引擎 把sku所有详情全部查出，封装到goods中
        CompletableFuture<SkuInfo> skuInfoFuture = CompletableFuture.supplyAsync(() -> {
            //1.1封装基本信息
            SkuInfo skuInfo = skuInfoMapper.selectById(skuId);
            goods.setId(skuInfo.getId());
            goods.setDefaultImg(skuInfo.getSkuDefaultImg());
//        goods.setCreateTime(new Date());//不在这里设置，以Es处理为准
            goods.setTitle(skuInfo.getSkuName());
            return skuInfo;
        }, executor);


        CompletableFuture<Void> priceFuture = CompletableFuture.runAsync(() -> {
            //1.2封装价格
            BigDecimal skuPrice = skuInfoMapper.getSkuPrice(skuId);
            goods.setPrice(skuPrice);
        }, executor);


        CompletableFuture<Void> tradeFuture = CompletableFuture.runAsync(() -> {
            //1.3封装品牌
            BaseTrademark baseTrademark = baseTrademarkMapper.getBaseTradeMarkBySkuId(skuId);
            goods.setTmId(baseTrademark.getId());
            goods.setTmName(baseTrademark.getTmName());
            goods.setTmLogoUrl(baseTrademark.getLogoUrl());
        }, executor);


        CompletableFuture<Void> categoryFuture = skuInfoFuture.thenAcceptAsync((skuInfo) -> {
            //1.4封装分类信息
            BaseCategory3 baseCategory3 = baseCategory3Mapper.selectById(skuInfo.getCategory3Id());
            goods.setCategory3Name(baseCategory3.getName());
            goods.setCategory3Id(baseCategory3.getId());
            BaseCategory2 baseCategory2 = baseCategory2Mapper.selectById(baseCategory3.getCategory2Id());
            goods.setCategory2Name(baseCategory2.getName());
            goods.setCategory2Id(baseCategory2.getId());
            BaseCategory3 baseCategory1 = baseCategory3Mapper.selectById(baseCategory2.getCategory1Id());
            goods.setCategory1Name(baseCategory1.getName());
            goods.setCategory1Id(baseCategory1.getId());
        }, executor);


        //1.5热度分，每次点击键入商品详情页一次就+1热度


        CompletableFuture<Void> searchAttrFuture = CompletableFuture.runAsync(() -> {
            //1.6 当商品对应的所有平台属性以及值
            List<SearchAttr> searchAttrs = skuAttrValueMapper.getBaseAttrAndValuesBySkuId(skuId);
            goods.setAttrs(searchAttrs);
        }, executor);


        CompletableFuture<Void> allFuture = CompletableFuture
                .allOf(skuInfoFuture, priceFuture,categoryFuture, tradeFuture, searchAttrFuture);

        allFuture.whenCompleteAsync((res, exc) -> {
            //远程调用检索服务，保存到ES
            skuEsFeignClient.saveSkuToEs(goods);
        }, executor);
        return true;
    }

    @Override
    public boolean cancelSale(Long skuId) {
        skuInfoMapper.updateSkuSaleStatus(skuId, 0);

        CompletableFuture.runAsync(() -> {
            // 2、把商品信息从搜索引擎移除
            skuEsFeignClient.deleteSkuFromEs(skuId);

        }, executor);

        return true;
    }

    @Override
    public List<Long> getAllId() {
        return skuInfoMapper.getAllId();
    }
}

